﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SemenQuest.Models
{
    public class Vector
    {
        public Vector()
        {
            _X = 0;
            _Y = 0;
        }
        public Vector(Double angle, Double size)
        {
            _X = Math.Cos(DegToRad(angle)) * size;
            _Y = Math.Sin(DegToRad(angle)) * size;
        }
        public Vector(Size size)
        {
            _X = size.Width;
            _Y = size.Height;
        }
        public Vector(Point point)
        {
            _X = point.X;
            _Y = point.Y;
        }

        private Double _X;
        private Double _Y;
        private Func<Double, Double> DegToRad = (angle) => Math.PI * angle / 180.0;

        public Double Angle
        {
            get { return MathUtils.AngleTowardTarget(Point.Empty, new Point((Int32)_X, (Int32)_Y)); }
            set
            {
                Double size = Size;
                _X = Math.Cos(DegToRad(value)) * size;
                _Y = Math.Sin(DegToRad(value)) * size;
            }
        }
        public Double Size
        {
            get { return MathUtils.DistanceToTarget(Point.Empty, new Point((Int32)_X, (Int32)_Y)); }
            set
            {
                Double angle = Angle;
                _X = Math.Cos(DegToRad(angle)) * value;
                _Y = Math.Sin(DegToRad(angle)) * value;
            }
        }
        public Double X
        {
            get { return _X; }
            set { _X = value; }
        }
        public Double Y
        {
            get { return _Y; }
            set { _Y = value; }
        }

        /// <summary>
        /// Returns a new vector with an angle inverted 180 degrees from the current instance
        /// </summary>
        /// <returns>Vector with angle inverted 180 degrees</returns>
        public Vector Invert()
        {
            Vector vec = new Vector();
            vec.X = -_X;
            vec.Y = -_Y;
            return vec;
        }
        public Point ToPoint()
        {
            return (Point)this;
        }
        public PointF ToPointF()
        {
            return (PointF)this;
        }
        public Size ToSize()
        {
            return (Size)this;
        }


        public static readonly Vector Empty = new Vector();

        public static Vector operator +(Vector v1, Vector v2)
        {
            v1 = new Vector(v1.X + v2.X, v1.Y + v2.Y);
            return v1;
        }
        public static Vector operator -(Vector v1, Vector v2)
        {
            v1 = new Vector(v1.X - v2.X, v1.Y - v2.Y);
            return v1;
        }
        public static Vector operator *(Vector v1, Vector v2)
        {
            v1 = new Vector(v1.X * v2.X, v1.Y * v2.Y);
            return v1;
        }
        public static Vector operator /(Vector v1, Vector v2)
        {
            v1 = new Vector(v1.X / v2.X, v1.Y / v2.Y);
            return v1;
        }


        public static implicit operator Point(Vector v1)
        {
            return new Point((Int32)v1.X, (Int32)v1.Y);
        }
        public static implicit operator Vector(Point p1)
        {
            return new Vector(p1);
        }
        public static implicit operator PointF(Vector v1)
        {
            return new PointF((float)v1.X, (float)v1.Y);
        }
        public static implicit operator Vector(PointF p1)
        {
            return new Vector(Point.Round(p1));
        }
        public static implicit operator Vector(Size s1)
        {
            return new Vector(s1);
        }
        public static implicit operator Size(Vector v1)
        {
            return new Size((Int32)v1.X, (Int32)v1.Y);
        }

    }
}
